<!--
 * @Author: aster lipian1004@163.com
 * @Date: 2025-02-20 17:12:02
 * @FilePath: \aster-flowable-uniapp\src\components\form\render\upload-image.vue
 * @Description: 图片
 * Copyright (c) 2025 by Aster, All Rights Reserved.
-->
<template>
  <van-field
    v-if="!_hidden"
    :name="formItemProp"
    :readonly="_readonly"
    :required="_required"
    :rules="_rules"
    :input-align="FieldInputAlignEnum.RIGHT"
    :error-message-align="FieldInputAlignEnum.RIGHT"
    :label-width="showLabel ? '' : '5rpx'"
  >
    <template #label>
      <text v-if="showLabel">{{ formItem.title }}</text>
    </template>
    <template #input>
      <van-uploader
        v-model="images"
        :multiple="formItem.props.maxNumber > 1"
        :max-count="formItem.props.maxNumber"
        :max-size="ImageUpload.maxSize * 1024 * 1024"
        accept="image/*"
        upload-text="选择图片"
        :disabled="_readonly"
        :before-read="beforeRead"
        :after-read="afterRead"
        :before-delete="beforeDelete"
        @delete="deleteImage"
      />
    </template>
  </van-field>
</template>
<script setup lang="ts">
  import { evaluateFormula } from '@/utils/workflow';
  import { computed, PropType, ref } from 'vue';
  import { isNotEmpty, isEmpty } from '@/utils/is';
  import { FormPermissionEnum } from '@/enums/workFlowEnum';
  import { FieldInputAlignEnum } from '@/enums/formEnum';
  import { ImageUpload } from '@/utils/config/fileConfig';
  import { uploadFile } from '@/utils/fileUtils';
  import { Toast } from '@/utils/uniapi/prompt';
  import { onLoad } from '@dcloudio/uni-app';

  const emit = defineEmits(['update:value']);
  const props = defineProps({
    value: {
      type: Array as PropType<WorkForm.FileModel[]>,
      default: () => [],
    },
    mode: {
      type: String as PropType<'design' | 'form' | 'search' | 'table' | 'print'>,
      default: 'design',
    },
    formData: {
      type: Object as PropType<WorkForm.FormDataModel>,
      default: {},
    },
    formItem: {
      type: Object as PropType<WorkComponent.ComponentConfig>,
      default: {},
    },
    tableId: {
      type: String,
      default: '',
    },
    tableIndex: {
      type: Number,
      default: 0,
    },
    showLabel: {
      type: Boolean,
      default: true,
    },
  });

  // 附件
  const images = ref<any>([]);

  /**
   * @description: 上传前校验
   * @param {any} rawFile 附件
   * @return {*}
   */
  const beforeRead = (rawFile) => {
    // 判断附件类型
    if (isEmpty(rawFile.type) || !ImageUpload.type.includes(rawFile.type)) {
      Toast('上传图片的格式不符合要求');
      return false;
    } else if (rawFile.size / 1024 / 1024 > ImageUpload.maxSize) {
      // 判断附件大小
      Toast('上传图片大小不能超过' + ImageUpload.maxSize + 'MB');
      return false;
    }
    return true;
  };

  /**
   * @description: 上传文件
   * @param {*} rawFile
   * @return {*}
   */
  const afterRead = (rawFile: any) => {
    if (Array.isArray(rawFile)) {
      rawFile.forEach((file) => {
        handleUploadFile(file);
      });
    } else {
      handleUploadFile(rawFile);
    }
  };

  /**
   * @description: 删除前校验
   * @return {*}
   */
  const beforeDelete = () => {
    if (_readonly.value) {
      return false;
    }
    return true;
  };

  /**
   * 删除附件
   * @param file 附件
   * @param detail 索引
   */
  const deleteImage = (file, detail) => {
    _value.value.splice(detail.index, 1);
  };

  /**
   * 上传附件
   * @param file 附件
   */
  const handleUploadFile = (rawFile: any) => {
    uploadFile(rawFile.file, (data) => {
      const imgObj: WorkForm.FileModel = {
        name: data.name,
        url: data.url,
      };
      _value.value.push(imgObj);
      images.value = JSON.parse(JSON.stringify(_value.value));
    });
  };

  // 键
  const formItemProp = computed(() => {
    if (isNotEmpty(props.tableId)) {
      return props.tableId + '.' + props.tableIndex + '.' + props.formItem.id;
    } else {
      return props.formItem.id;
    }
  });

  /**
   * @description: 组件值
   */
  const _value = computed({
    get() {
      return props.value;
    },
    set(val) {
      emit('update:value', val);
    },
  });

  /**
   * @description: 是否必填, true-必填
   */
  const _required = computed(() => {
    return props.formItem.props.required;
  });

  /**
   * @description: 是否只读, true-只读
   */
  const _readonly = computed(() => {
    let r = props.formItem.props.readonly;
    if (props.formItem.operation && props.formItem.operation.length > 0) {
      r = r || props.formItem.operation[0] == FormPermissionEnum.READONLY;
    }
    return r;
  });

  /**
   * @description: 校验规则
   */
  const _rules = computed(() => {
    const isRequired = _required.value;
    if (props.mode != 'form') {
      return [];
    }
    return isRequired ? [{ required: true, message: `请输入${props.formItem.title}` }] : [];
  });

  /**
   * @description: 是否隐藏, true-隐藏
   */
  const _hidden = computed(() => {
    let r = false;
    // 解析隐藏条件公式
    if (props.formItem.props.hidden) {
      let expression = props.formItem.props.hidden;
      // 如果是子表中的控件，则需要用到下标
      if (isNotEmpty(props.tableId)) {
        expression = expression.replaceAll('?', props.tableIndex);
      }
      r = evaluateFormula(expression, props.formData);
    }
    // 判断流程节点下该控件是否隐藏
    if (props.formItem.operation && props.formItem.operation.length > 0) {
      r = r || props.formItem.operation[0] == FormPermissionEnum.HIDDEN;
    }
    return r;
  });

  onLoad(() => {
    if (_value.value && _value.value.length > 0) {
      images.value = _value.value.map((item) => {
        return {
          name: item.name,
          url: item.url,
        };
      });
    }
  });

  defineExpose({
    _hidden,
  });
</script>
<style scoped lang="scss"></style>
